#include "TcpServer.hpp"

#include <iostream>
#include <memory>

using namespace tcpserver;

static void usage(std::string proc)
{
    std::cerr << "Usage:\n\t" << proc << " port"
              << "\n\n";
}

bool cal(const request &req, response &resp)
{
    resp._exitcode = OK;
    resp._result = OK;
    resp._msg = "正常结果, nice!";
    switch (req._op)
    {
    case '+':
        resp._result = req._x + req._y;
        break;
    case '-':
        resp._result = req._x - req._y;
        break;
    case '*':
        resp._result = req._x * req._y;
        break;
    case '/':
    {
        if (req._y == 0)
        {
            resp._msg = "你都除零啦, 还要啥结果呢！";
            resp._exitcode = DIV_ZERO;
        }
        else
            resp._result = req._x + req._y;
    }
    break;
    case '%':
    {
        if (req._y == 0)
        {
            resp._msg = "你都模零啦，还要啥结果呢！";
            resp._exitcode = MOD_ZERO;
        }
        else
            resp._result = req._x % req._y;
    }
    break;
    default:
    {
        resp._exitcode = OP_ERROR;
        resp._msg = "操作符都出错了，长点心吧！好好检查一下";
    }
    break;
    }
}

void service(Connection *conn)
{
    std::string onePackage = "\0";
    while (ParseOnePackage(conn->_inbuffer, &onePackage))
    {
        // 读到一个完整报文
        std::cout << "读到一个完整报文: \n"
                  << onePackage;

        // 1. 去掉报头及其他无关信息
        std::string reqStr;
        if (!deLength(onePackage, &reqStr))
            return;

        std::cout << "不带报头的请求 :\n"
                  << reqStr;

        // 2. 反序列化
        request req;
        if (!req.deserialize(reqStr))
            return;

        // 3. 计算结果
        response resp;
        cal(req, resp);

        // 4. 对结果进行序列化
        string respStr;
        resp.serialize(&respStr);

        // 5.发送数据(发送之前添加报头)
        conn->_outbuffer = enLength(respStr); // 添加到发送缓冲区中，相当于入队列
        std::cout << "-------------添加响应报文的报头为  \n"
                  << conn->_outbuffer;
    }

    // 这里直接发，先试试水，看看能不能一次性发完了，发完了就皆大欢喜，发不完后面再处理
    // 因为服务器刚启动时，发送缓冲区是空的，发送事件是一直就绪的，只有当我们发送失败了，才需要让epoll模型帮我们关心发送事件是否就绪
    logMessage(DEBUG, "conn->_outbuffer: %d Bytes", conn->_outbuffer.size());
    if (conn->_sender)
        conn->_sender(conn);

    // 走到这，如果没有发完，就需要开启对应的sockfd的读事件的关心
    // 下面这部分代码也可以写到TcpServer的Sender()中，效果可能更好一点
    // if (!conn->_outbuffer.empty())
    //     conn->_tsp->EnableReadWrite(conn, true, true); // 开启对读事件的关心
    // else
    //     conn->_tsp->EnableReadWrite(conn, true, false);
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        usage(argv[0]);
        exit(USAGE_ERR);
    }

    uint16_t port = atoi(argv[1]);

    std::unique_ptr<TcpServer> tsvr(new TcpServer(service, port));

    tsvr->InitServer();

    tsvr->Dispatcher();

    return 0;
}